package server

import (
	"fmt"

	"gddgame.cc/galaxy/asteroid"
	"gddgame.cc/galaxy/binocle"
	. "gddgame.cc/galaxy/common/dsl/web"
	"gddgame.cc/galaxy/server/composer"
	"gddgame.cc/galaxy/server/web"
	"gddgame.cc/galaxy/utils"
)

const PluginName = "server"

func init() {
	RegisterPlugin(PluginProvider{
		Name: PluginName,

		OnInit: func(builder composer.Builder, core binocle.CoreClient) error {
			core.OnStarted(func() {
				fmt.Println("core on started")
				core.Watching("nodes", func(message asteroid.Message) {
					fmt.Println("noodes", core.NodeAll())
					message.Response(core.NodeAll())
				})
				core.Watching("servers", func(message asteroid.Message) {
					t := message.Data().(string)
					observers := core.Observers(t)
					result := make([]map[string]interface{}, len(observers))
					index := 0
					for key, nodes := range observers {
						nodeList := make([]map[string]interface{}, len(nodes))
						for i, node := range nodes {
							nodeList[i] = map[string]interface{}{
								"node": node,
								"meta": core.Meta(node),
							}
						}
						server := make(map[string]interface{})
						server["name"] = key
						server["nodes"] = nodeList
						result[index] = server
						index += 1
					}
					message.Response(result)
				})
				core.Watching("server/nodes", func(message asteroid.Message) {
					server := message.Data().(string)
					group := message.List()[1].(string)
					nodes := core.NodeList(server)
					fmt.Println("server/nodes", nodes, group)
					message.Response(nodes)
				})
				core.Watching("server/reload/node", func(message asteroid.Message) {
					server := message.Data().(string)
					var node string
					nodeI := message.Read(1)
					if nodeI != nil {
						node = utils.ToString(node)
					}
					core.Reload(server, node)
					message.Response(true)
				})
			})
			return nil
		},
		BindRouter: BindRouter,
	})
}

func BindRouter(builder composer.Builder, core binocle.CoreClient, r *SwaggerRouter) {
	r.Get("/dcs", Swagger{
		Controller: func(context web.Context) (map[string]string, error) {
			// 获取所有集群信息
			result := map[string]string{}
			dcs := core.ListDC()
			for _, dc := range dcs {
				result[dc] = core.GetWan(dc)
			}
			return result, nil
		},
		Params:   []Param{},
		Response: ApiResponse,
	})
	r.Get("/nodes", Swagger{
		Controller: func(context web.Context, dc string) (interface{}, error) {
			var result interface{}
			var err error
			wait := make(chan struct{}, 1)
			core.PublishPipe().Cross(map[string]string{dc: core.Name()}).CallbackTo(func(success bool, data interface{}) {
				if success {
					result = data
				} else {
					err = ValidException("Target Fail")
				}
				wait <- struct{}{}
			}).Send("nodes")
			<-wait
			return result, err
		},
		Params: []Param{
			{Name: "dc", In: Query, Required: true, Default: binocle.DefaultDataCenter},
		},
		Response: ApiResponse,
	})
	r.Get("/servers", Swagger{
		Controller: func(context web.Context, t string, dc string) (interface{}, error) {
			var result interface{}
			var err error
			wait := make(chan struct{}, 1)
			core.PublishPipe().Cross(map[string]string{dc: core.Name()}).Data(t).CallbackTo(func(success bool, data interface{}) {
				if success {
					result = data
				} else {
					err = ValidException("Target Fail")
				}
				wait <- struct{}{}
			}).Send("servers")
			<-wait
			return result, err
		},
		Params: []Param{
			{Name: "type", In: Query, Required: true},
			{Name: "dc", In: Query, Required: true, Default: core.DC()},
		},
		Response: ApiResponse,
	})
	r.Get("/server/{server}/nodes", Swagger{
		Controller: func(context web.Context, server string, dc string, group string) (interface{}, error) {
			var result interface{}
			var err error
			wait := make(chan struct{}, 1)
			core.PublishPipe().Cross(map[string]string{dc: core.Name()}).List(server, group).CallbackTo(func(success bool, data interface{}) {
				if success {
					result = data
				} else {
					err = ValidException("Target Fail")
				}
				wait <- struct{}{}
			}).Send("server/nodes")
			<-wait
			return result, err
		},
		Params: []Param{
			{Name: "server", In: Path, Required: true},
			{Name: "dc", In: Query, Required: true, Default: core.DC()},
			{Name: "group", In: Query},
		},
		Response: ApiResponse,
	})
	r.Put("/server/{server}/reload/node", Swagger{
		Controller: func(context web.Context, server string, dc string, node string) (interface{}, error) {
			var result interface{}
			var err error
			wait := make(chan struct{}, 1)
			core.PublishPipe().Cross(map[string]string{dc: ""}).List(server, node).CallbackTo(func(success bool, data interface{}) {
				if success {
					result = data
				} else {
					err = ValidException("Target Fail")
				}
				wait <- struct{}{}
			}).Send("server/reload/node")
			<-wait
			return result, err
		},
		Params: []Param{
			{Name: "server", In: Path, Required: true},
			{Name: "dc", In: Body, Required: true, Default: core.DC()},
			{Name: "node", In: Body, Required: true},
		},
		Response: ApiResponse,
	})
}
